﻿using System.Collections.Generic;
using System;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
using System.Text;
using FRMS.Model;
using Newtonsoft.Json;

namespace FRMS.BUS
{
    public class NetBUS
    {
        public void RunCommand(string command)
        {
            Process.Start("sudo", command);
        }

        public bool UpdateNetInfo(List<NetInfo> netInfos)
        {
            try
            {
                //RunCommand("chmod 777 /etc/netplan/01-network-manager-all.yaml");
                //using (FileStream fileStream = new FileStream("/etc/netplan/01-network-manager-all.yaml", FileMode.Open, FileAccess.Write, FileShare.Write))
                RunCommand("chmod 777 /etc/netplan/00-installer-config.yaml");
                using (FileStream fileStream = new FileStream("/etc/netplan/00-installer-config.yaml", FileMode.Open, FileAccess.Write, FileShare.Write))
                {
                    fileStream.Seek(0, SeekOrigin.Begin);
                    fileStream.SetLength(0);
                    using (StreamWriter streamWriter = new StreamWriter(fileStream))
                    {
                        streamWriter.WriteLine("network:");
                        streamWriter.WriteLine("  version: 2");
                        streamWriter.WriteLine("  ethernets:");
                        foreach (var item in netInfos)
                        {
                            if (string.IsNullOrEmpty(item.IP))
                            {
                                streamWriter.WriteLine("    " + item.NetWorkName + ":");
                                streamWriter.WriteLine("      dhcp4: yes");
                            }
                            else
                            {
                                streamWriter.WriteLine("    " + item.NetWorkName + ":");
                                streamWriter.WriteLine("      dhcp4: false");
                                streamWriter.WriteLine("      addresses: [" + item.IP + "/" + MaskToInt(item.Mask) + "]");
                                streamWriter.WriteLine("      gateway4: " + item.GateWay);
                            }

                            if (string.IsNullOrEmpty(item.DNS))
                            {
                                item.DNS = "8.8.8.8";
                            }

                            streamWriter.WriteLine("      nameservers:");
                            streamWriter.WriteLine("        addresses: [" + item.DNS + "]");
                        }

                        fileStream.Flush();
                        streamWriter.Close();
                    }

                    fileStream.Close();
                }
                RunCommand("netplan apply");
                return true;
            }
            catch (Exception ex)
            {
                LogHelper.Log(ex.ToString());
                return false;
            }
        }

        public List<NetInfo> GetNetInfo()
        {
            List<NetInfo> netInfos = new List<NetInfo>();
            List<NetInfo> list = new List<NetInfo>();
            try
            {
                netInfos = GetAllNetPort();
                //StreamReader reader = new StreamReader(@"/etc/netplan/01-network-manager-all.yaml", Encoding.Default);
                StreamReader reader = new StreamReader(@"/etc/netplan/00-installer-config.yaml", Encoding.Default);
                string theReply = reader.ReadToEnd();
                reader.Close();
                foreach (var item in netInfos)
                {
                    try
                    {
                        NetInfo info = new NetInfo();
                        info.NetWorkName = item.NetWorkName;
                        Regex strRegex = new Regex(string.Format(@"(?<str>([^\w\s]+|\s*){0}:\s*dhcp4: false([\w\W]*))", item.NetWorkName));
                        Regex addressRegex = new Regex(@"([^\w\s]+|\s*)addresses:\s*[^\w\s](?<address>\d+.\d+.\d+.\d+/\d+)]\s*");
                        Regex gatewayRegex = new Regex(@"([^\w\s]+|\s*)gateway4:\s*(?<gateway>\d+.\d+.\d+.\d+)\s*");
                        Regex maskReg = new Regex(@"\d+.\d+.\d+.\d+/(?<mask>\d+)\s*");
                        Regex ipRegex = new Regex(@"\s*(?<ip>\d+.\d+.\d+.\d+)\s*");
                        Regex dnsRegex = new Regex(@"(?<routes>([^\w\s]+|\s*)nameservers:([\w\W]*))");
                        Regex dns_addressRegex = new Regex(@"([^\w\s]+|\s*)addresses:\s*[^\w\s](?<dnsaddress>\d+.\d+.\d+.\d+)]\s*");
                        MatchCollection strCollection = strRegex.Matches(theReply);

                        if (strCollection.Count > 0)
                        {
                            string str_value = strCollection[0].Groups["str"].Value;
                            MatchCollection addressCollection = addressRegex.Matches(str_value);
                            MatchCollection gatewayCollection = gatewayRegex.Matches(str_value);
                            MatchCollection dnsCollection = dnsRegex.Matches(str_value);
                            if (addressCollection.Count > 0)
                            {
                                string str = addressCollection[0].Groups["address"].Value.Trim();
                                string ip = ipRegex.Matches(str)[0].Groups["ip"].Value.Trim();
                                info.IP = ip;
                                int mask = Convert.ToInt32(maskReg.Matches(str)[0].Groups["mask"].Value.Trim());
                                string Mask = GetMask(mask);
                                info.Mask = Mask;

                                if (gatewayCollection.Count > 0)
                                {
                                    string str_4 = gatewayCollection[0].Groups["gateway"].Value.Trim();
                                    string ip_4 = ipRegex.Matches(str_4)[0].Groups["ip"].Value.Trim();
                                    info.GateWay = ip_4;
                                }

                                MatchCollection routesstrCollection = dnsRegex.Matches(str_value);
                                if (routesstrCollection.Count > 0)
                                {
                                    string routestr_value = routesstrCollection[0].Groups["routes"].Value;
                                    MatchCollection route_addressCollection = dns_addressRegex.Matches(routestr_value);

                                    if (route_addressCollection.Count > 0)
                                    {
                                        string str_3 = route_addressCollection[0].Groups["dnsaddress"].Value.Trim();
                                        string ip_3 = ipRegex.Matches(str_3)[0].Groups["ip"].Value.Trim();
                                        info.DNS = ip_3;
                                    }
                                }
                                list.Add(info);
                            }
                        }
                    }
                    catch
                    {
                        continue;
                    }
                }

                return list;
            }
            catch (Exception ex)
            {
                LogHelper.Log(ex.ToString());
                return netInfos;
            }
        }

        public List<NetInfo> GetAllNetPort()
        {
            List<NetInfo> netInfos = new List<NetInfo>();
            try
            {
                var process = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName = "/bin/bash",
                        Arguments = "-c \"ip link show\"",
                        RedirectStandardOutput = true,
                        UseShellExecute = false,
                        CreateNoWindow = true,
                    }
                };
                process.Start();
                string output = process.StandardOutput.ReadToEnd();
                process.WaitForExit();
                Regex regex = new Regex(@"(?<str>([^\w\s]+|)enp\ds0([\w\s]+|\s*))");
                MatchCollection strCollection = regex.Matches(output);
                if (strCollection.Count > 0)
                {
                    for (int i = 0; i < strCollection.Count; i++)
                    {
                        NetInfo netInfo = new NetInfo();
                        netInfo.NetWorkName = strCollection[i].Groups["str"].Value;
                        netInfos.Add(netInfo);
                    }
                }
            }
            catch
            {

            }
            return netInfos;
        }

        public string GetMask(int value)
        {
            try
            {
                string str = string.Empty;
                for (int i = 0; i < value; i++)
                {
                    str += "1";
                }
                str = str.PadRight(32, '0');
                string a = Convert.ToInt32(str.Substring(0, 8), 2).ToString() + "." + Convert.ToInt32(str.Substring(8, 8), 2).ToString() + "." + Convert.ToInt32(str.Substring(16, 8), 2).ToString() + "." + Convert.ToInt32(str.Substring(24, 8), 2).ToString();
                return a;
            }
            catch
            {
                return "0.0.0.0";
            }
        }

        public string MaskToInt(string mask)
        {
            string value = string.Empty;
            string[] array = mask.Replace(" ", "").Split('.');
            for (int i = 0; i < array.Length; i++)
            {
                value += Convert.ToString(Convert.ToInt32(array[i]), 2);
            }
            value = value.PadRight(32, '0');

            string keyWord = "1";
            int index = 0;
            int count = 0;
            while ((index = value.IndexOf(keyWord, index)) != -1)
            {
                count++;
                index = index + keyWord.Length;
            }
            return count.ToString();
        }

        public string GetNtpIp()
        {
            try
            {
                StreamReader reader = new StreamReader(@"/etc/systemd/timesyncd.conf", Encoding.Default);
                string theReply = reader.ReadToEnd();
                reader.Close();
                //                string theReply = @"#  This file is part of systemd.
                //#
                //#  systemd is free software; you can redistribute it and/or modify it
                //#  under the terms of the GNU Lesser General Public License as published by
                //#  the Free Software Foundation; either version 2.1 of the License, or
                //#  (at your option) any later version.
                //#
                //# Entries in this file show the compile time defaults.
                //# You can change settings by editing this file.
                //# Defaults can be restored by simply deleting this file.
                //#
                //# See timesyncd.conf(5) for details.

                //[Time]
                //NTP=www.baidu.com
                //#FallbackNTP=ntp.ubuntu.com
                //#RootDistanceMaxSec=5
                //#PollIntervalMinSec=32
                //#PollIntervalMaxSec=2048";
                Regex addressRegex = new Regex(@"\nNTP=(?<ip>\S*)");

                MatchCollection addressCollection = addressRegex.Matches(theReply);
                string str = addressCollection[0].Groups["ip"].Value.Trim();

                return str;
            }
            catch
            {
                return "";
            }
        }

        public bool SetNtp(string ipAddress)
        {
            try
            {
                RunCommand("chmod 777 /etc/systemd/timesyncd.conf");
                using (FileStream fs = new FileStream("/etc/systemd/timesyncd.conf", FileMode.Open, FileAccess.Write))
                {
                    StreamWriter sw = new StreamWriter(fs);
                    sw.BaseStream.Seek(0, SeekOrigin.Begin);
                    sw.BaseStream.SetLength(0);
                    sw.WriteLine("[Time]");
                    sw.WriteLine("NTP=" + ipAddress);
                    sw.WriteLine("#FallbackNTP=ntp.ubuntu.com");
                    sw.WriteLine("RootDistanceMaxSec=5");
                    sw.WriteLine("PollIntervalMinSec=32");
                    sw.WriteLine("PollIntervalMaxSec=2048");
                    sw.Flush();
                    sw.Close();
                    fs.Close();
                }
                RunCommand("systemctl restart systemd-timesyncd");
                return true;
            }
            catch (Exception e)
            {
                LogHelper.Log(e.ToString());
                return false;
            }
        }

        public bool CalibrationTime(string time)
        {
            try
            {
                RunCommand("date -s \"" + time + "\"");
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}
